package org.hsieh.tr.explore.ui;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.layout.GridLayoutFactory;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.TreeColumn;
import org.eclipse.ui.part.ViewPart;
import org.hsieh.tr.explore.db.ETranscanIsolationLevel;
import org.hsieh.tr.explore.db.ISqlCommand;

public class SQLHistoryView extends ViewPart implements PropertyChangeListener {

    public static final String ID = "org.hsieh.tr.explore.HistoryView";

    private TreeViewer viewer;

    public SQLHistoryView() {

    }

    @Override
    public void createPartControl(Composite parent) {
	GridLayoutFactory.swtDefaults().margins(0, 0).numColumns(1).applyTo(
		parent);

	viewer = new TreeViewer(parent, SWT.FULL_SELECTION | SWT.MULTI);
	viewer.getTree().setHeaderVisible(true);
	viewer.getTree().setLinesVisible(true);

	viewer.setContentProvider(new HistoryContentProvider());
	viewer.setLabelProvider(new HistoryLabelProvider());

	GridDataFactory.fillDefaults().grab(true, true).applyTo(
		viewer.getTree());

	createColumn("SQL command", 360);
	createColumn("Transaction Level", 240);
	createColumn("Time", 240);

	SQLCommandManager.getInstance().addPropertiesListener(this);
	viewer.setInput(SQLCommandManager.getInstance());

	registerPopupMenu();

    }

    private void createColumn(String label, int width) {
	TreeColumn column = new TreeColumn(viewer.getTree(), SWT.CENTER);
	column.setText(label);
	column.setWidth(width);
    }

    @Override
    public void setFocus() {
	viewer.getTree().setFocus();
    }

    public void propertyChange(PropertyChangeEvent evt) {
	viewer.refresh();
    }

    private void registerPopupMenu() {
	MenuManager popupMenuManager = new MenuManager("#PopupMenu");
	popupMenuManager.setRemoveAllWhenShown(true);
	Menu popupMenu = popupMenuManager.createContextMenu(viewer.getTree());
	viewer.getTree().setMenu(popupMenu);
	getSite().setSelectionProvider(viewer);
	getSite().registerContextMenu(popupMenuManager, viewer);
    }

    private class HistoryContentProvider implements ITreeContentProvider {

	@SuppressWarnings("unchecked")
	public Object[] getElements(Object inputElement) {
	    if (inputElement instanceof SQLCommandManager) {
		Object[] array = ((SQLCommandManager) inputElement)
			.getCommands().toArray(new Object[0]);
		Arrays.sort(array);
		return array;
	    } else if (inputElement instanceof List) {
		return ((List) inputElement).toArray(new Object[0]);
	    } else
		return null;
	}

	public void dispose() {

	}

	public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {

	}

	public Object[] getChildren(Object parentElement) {
	    if (parentElement instanceof SQLCommandManager) {
		return ((SQLCommandManager) parentElement).getCommands()
			.toArray(new Object[0]);
	    }
	    return null;
	}

	public Object getParent(Object element) {
	    return null;
	}

	public boolean hasChildren(Object element) {
	    if (element instanceof SQLCommandManager) {
		return !((SQLCommandManager) element).getCommands().isEmpty();
	    }
	    return false;
	}

    }

    private class HistoryLabelProvider extends LabelProvider implements
	    ITableLabelProvider {

	public Image getColumnImage(Object element, int columnIndex) {
	    switch (columnIndex) {
	    case 0:
		return ResourceHandler.getInstance().getImage(
			"icons/history-16x16.png");
	    case 2:
		return ResourceHandler.getInstance().getImage(
			"icons/clock-16x16.png");
	    default:
		return null;
	    }
	}

	public String getColumnText(Object element, int columnIndex) {
	    if (element instanceof SQLCommandManager) {
		return "SQL Commands";
	    }

	    if (element instanceof ISqlCommand) {
		ISqlCommand command = (ISqlCommand) element;
		switch (columnIndex) {
		case 0:
		    return command.getSqlExpression();
		case 1:
		    return ETranscanIsolationLevel.getLevelBy(
			    command.getIsolcationLevelWhenExecute())
			    .getLevelName();
		case 2:
		    return String.format("%1$tm/%1$te/%1$tY %1$tH:%1$tM:%1$tS",
			    new Date(command.getExecuteTime()));
		default:
		    break;
		}
	    }
	    return null;
	}

    }
}
